package com.cbtx.module_sp.ui.vm

import android.app.Application
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.Build
import android.os.Handler
import android.telephony.TelephonyManager
import android.text.TextUtils
import android.util.Log
import androidx.lifecycle.MutableLiveData
import com.cbtx.module.base.ContextManager
import com.cbtx.module.base.SpUtils
import com.cbtx.module.base.http.HttpBaseBean
import com.cbtx.module.base.http.HttpManager
import com.cbtx.module.base.http.MyRequestCallBack
import com.cbtx.module.base.vm.BaseVM
import com.cbtx.module.common.bean.BannerBean
import com.cbtx.module.common.bean.request.StoreInfoEntity
import com.cbtx.module.common.http.HttpUrlManager
import com.cbtx.module_sp.MachineFactory
import com.cbtx.module_sp.MyApplication
import com.cbtx.module_sp.R
import com.cbtx.module_sp.bean.*
import com.cbtx.module_sp.event.ChangeAdvEvent
import com.cbtx.module_sp.interceptor.HeaderInterceptor
import com.google.gson.Gson
import com.liulishuo.filedownloader.BaseDownloadTask
import com.liulishuo.filedownloader.FileDownloadSampleListener
import com.liulishuo.filedownloader.FileDownloader
import com.liulishuo.filedownloader.util.FileDownloadUtils
import com.txcb.lib.base.utils.*
import org.greenrobot.eventbus.EventBus
import java.io.File
import java.lang.reflect.Method

class MainVM(application: Application) : BaseVM(application) {

    companion object {
        val bannerItemList: MutableList<BannerBean.BannerItem> = ArrayList()
        const val TAG = "MainVM"
    }

    var version = ""
    var mQrCodeBitmap: Bitmap? = null
    var logoBitmap: Bitmap? = null
    val reportResult: MutableLiveData<Boolean> = MutableLiveData()
    val pollReportIntervalTime: MutableLiveData<Int> = MutableLiveData()
    val pollUpgradeIntervalTime: MutableLiveData<Int> = MutableLiveData()
    val storeInfoEntity: MutableLiveData<StoreInfoEntity> = MutableLiveData()

    private val delayRequestTime = 120

    fun init() {
        replyUpgrade()
    }

    /**
     * 回复服务器升级信息
     */
    private fun replyUpgrade() {
        val url = "${HttpUrlManager.getUpgradeReply}"
        var map = mutableMapOf<String, Any>()
        map["serialNo"] = SpUtils.getString(SpUtils.NEW_UPGRADE_UPDATE_TIME)
        map["packageName"] = packageName(MyApplication.instance)

        HttpManager.getInstance("", HeaderInterceptor(MyApplication.instance.getHeaderMap()))
            .sendPost(url, map, object : MyRequestCallBack<SimpleResponse>() {
                override fun onSuccess(versionBean: SimpleResponse?) {

                }

                override fun onFailure(error: Int, msg: String?) {

                }
            })

    }

    fun requestWxQrCode() {

        logoBitmap =
            BitmapFactory.decodeResource(mApplication.resources, R.drawable.ic_logo_qr_code)
        val url = HttpUrlManager.DEVICE_WXQRCODE + DeviceUtil.getSerialNumber(mApplication)

        mQrCodeBitmap = ZxingUtils.createQRCode(url, 340, logoBitmap)

    }


    fun ubindQrCode(): Bitmap? {
        val wh: Int = ContextManager.getContext().resources.getDimensionPixelSize(R.dimen.dp_400)
        val iMachine: IMachine =
            MachineFactory.getAutoCreate(MyApplication.instance)
        val url: String = ContextManager.getContext().getString(
            R.string.register_qr,
            "t.mj.linkzl.com",
            if (TextUtils.isEmpty(Build.getSerial())) "" else Build.getSerial(),
            MachineFactory.getAutoCreate(ContextManager.getContext()).uniqueDeviceCode,
            "INTERACTIVE",
            iMachine.getLocalMac(),
            iMachine.getModel()
        )
        return ZxingUtils.createQRCode(
            url,
            wh,
            BitmapFactory.decodeResource(mApplication.resources, R.drawable.ic_logo_qr_code)
        )
    }

    //检查版本
    fun checkVersion() {
        val url = "${HttpUrlManager.APP_VERSION}"
        var map = mutableMapOf<String, Any>()
        map["packageName"] = packageName(MyApplication.instance)
        HttpManager.getInstance(
            "",
            HeaderInterceptor(MyApplication.instance.getHeaderMap())
        )
            .sendPost(url, map, object : MyRequestCallBack<UpgradeInfoEntity>() {
                override fun onSuccess(versionBean: UpgradeInfoEntity?) {
                    if (versionBean?.data != null && versionBean.data.size > 0) {
                        for (upgradeInfo in versionBean.data) {
                            when (upgradeInfo.upgradeType) {
                                0 -> downloadApk(upgradeInfo.url)
                                else -> {
                                }
                            }
                        }
                    }
                }

                override fun onFailure(error: Int, msg: String?) {

                }
            })
    }

    private fun packageName(context: Context): String {
        val manager = context.packageManager
        var name = ""
        try {
            val info = manager.getPackageInfo(context.packageName, 0)
            name = info.applicationInfo.packageName
        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
        }
        return name
    }

    //检查广告
    fun checkAdvBanner() {
        requestBanner()
        Handler().postDelayed({
            checkAdvBanner()
        }, 1000 * 60 * 10)
    }


    /**
     * 上传经纬度
     */
    fun requestPadLog(padLogRequestBean: PadLogRequestBean) {
        val url = HttpUrlManager.REQUST_PAD_LOG
        val json = Gson().toJson(padLogRequestBean)

        HttpManager.getInstance("", null)
            .sendPostJson(url, json, object : MyRequestCallBack<HttpBaseBean?>() {
                override fun onSuccess(obj: HttpBaseBean?) {}
                override fun onFailure(error: Int, msg: String?) {}
            })
    }

    //这是要静默安装的
    private fun downloadApk(downloadUrl: String) {

        if (TextUtils.isEmpty(downloadUrl)) {
            return
        }
        val indext = downloadUrl.lastIndexOf("/") + 1
        val fileName = downloadUrl.substring(indext)
        val filePath: String = FileUtils.getDownloadDir()
        val allPath = "$filePath$fileName"

        FileDownloader.setup(mApplication)
        FileDownloader.getImpl().create(downloadUrl)
            .setPath(filePath + fileName, false)
            .setListener(object : FileDownloadSampleListener() {
                override fun pending(task: BaseDownloadTask, soFarBytes: Int, totalBytes: Int) {
                    super.pending(task, soFarBytes, totalBytes)
                    Log.d(TAG, "pending")
                }

                override fun progress(task: BaseDownloadTask, soFarBytes: Int, totalBytes: Int) {
                    super.progress(task, soFarBytes, totalBytes)
//                    (task.tag as ViewHolder).updateProgress(soFarBytes, totalBytes, task.speed)
                    Log.d(TAG, "progress")
                }

                override fun error(task: BaseDownloadTask, e: Throwable) {
                    super.error(task, e)
//                    (task.tag as ViewHolder).updateError(e, task.speed)
                    Log.d(TAG, "error")
                }

                override fun connected(
                    task: BaseDownloadTask,
                    etag: String,
                    isContinue: Boolean,
                    soFarBytes: Int,
                    totalBytes: Int
                ) {
                    super.connected(task, etag, isContinue, soFarBytes, totalBytes)
                    Log.d(TAG, "connected")
                }

                override fun paused(task: BaseDownloadTask, soFarBytes: Int, totalBytes: Int) {
                    super.paused(task, soFarBytes, totalBytes)
                    Log.d(TAG, "paused")
                }

                override fun completed(task: BaseDownloadTask?) {
                    super.completed(task)
                    Handler().postDelayed({ //进入安装
                        if (checkIsCanGou("com.cbtx.app_manager")) {
                            val intent: Intent =
                                mApplication.packageManager.getLaunchIntentForPackage("com.cbtx.app_manager")!!
                            mApplication.startActivity(intent)
                        }
                        InstallApkUtil.installSilent(allPath)
                    }, 2000)
                }
            }).start()
    }


    private fun checkIsCanGou(launchItent: String): Boolean {
        return File("/data/data/$launchItent").exists()
    }


    //这是普通安装的
    private fun downloadApk2(downloadUrl: String) {
        if (TextUtils.isEmpty(downloadUrl)) {
            return
        }
        val indext = downloadUrl.lastIndexOf("/") + 1
        val fileName = downloadUrl.substring(indext)
        val filePath: String = FileUtils.getDownloadDir()
        val allPath = "$filePath/$fileName"
        HttpManager.getInstance("", null)
            .downloadFile(downloadUrl, filePath, fileName, object : HttpManager.OnDownloadListener {
                override fun onDownloadSuccess(path: String?) {
                    Handler().postDelayed({ //进入安装
                        InstallApkUtil.installSilent(allPath)
                    }, 2000)
                }

                override fun onDownloading(progress: Int) {
                    LogUtil.d("progress:$progress")
                }

                override fun onDownloadFailed() {}
            })
    }


    val advBannerList: MutableList<BannerBean.BannerItem> = ArrayList()
    val oldAdvBannerList: MutableList<BannerBean.BannerItem> = ArrayList()

    fun requestBanner() {
        val deviceTypeName = "1280800"
        val areaId = SharedPreferencesUtils.loadint("areaId")
        val url = "${HttpUrlManager.BANNER_DEVICE}$deviceTypeName/$areaId"

        LogUtil.d("AdvActivityVM${url}")

        HttpManager.getInstance("", null)
            .sendGet(url, HashMap(), object : MyRequestCallBack<BannerBean>() {
                override fun onSuccess(obj: BannerBean?) {
                    advBannerList.clear()
                    resetData(obj)
                    downLoadAdvBanner(0)
                }

                override fun onFailure(error: Int, msg: String?) {
                    Handler().postDelayed({
                        requestBanner()
                    }, 1000 * 60)
                }
            })
    }


    fun resetData(obj: BannerBean?) {
        if (obj?.data != null) {

            for (bannerItem in obj?.data) {
                bannerItem.bannerImgurl = "${obj.imgUrl}${bannerItem.bannerImgurl}"
            }

            advBannerList.addAll(obj.data)
        }
    }


    fun downLoadAdvBanner(position: Int) {
        if (advBannerList.size <= 0 || advBannerList.size <= (position)) {

            if (checkAdvVersion()) {

                oldAdvBannerList.clear()
                oldAdvBannerList.addAll(advBannerList)


                val changeAdvEvent = ChangeAdvEvent()
                changeAdvEvent.bannerItemList?.addAll(advBannerList)
                EventBus.getDefault().post(changeAdvEvent)
            }
            return
        }


        loadVideo(position)

    }


    fun checkAdvVersion(): Boolean {
        if (oldAdvBannerList.size != advBannerList.size) {
            return true
        }
        val size = oldAdvBannerList.size

        for (i in 0..size) {
            val bannerItem1: BannerBean.BannerItem = oldAdvBannerList[i]
            val bannerItem2: BannerBean.BannerItem = advBannerList[i]

            if (bannerItem1.bannerImgurl != bannerItem2.bannerImgurl) {
                return true
            }
        }


        return false
    }

    fun loadVideo(position: Int) {

        val advBanner = advBannerList[position]
        val downloadUrl = advBanner.bannerImgurl
        if (TextUtils.isEmpty(downloadUrl)) {
            return
        }
        val indext = downloadUrl.lastIndexOf("/") + 1
        val fileName = downloadUrl.substring(indext)
        val filePath: String = FileUtils.getDownloadDir()

        val downloadName = MD5Util.setString(downloadUrl)
        val downloadSavePath = "$filePath$downloadName"
        val allPath = "$filePath$fileName"

        LogUtil.d("============================================================================")
        LogUtil.d("downloadUrl${downloadUrl}")
        LogUtil.d("fileName${fileName}")
        LogUtil.d("filePath${filePath}")
        LogUtil.d("downloadName${downloadName}")
        LogUtil.d("downloadSavePath${downloadSavePath}")
        LogUtil.d("allPath${allPath}")
        LogUtil.d("============================================================================")

        //
        val videoFile = File(allPath)
        if (videoFile.exists()) {
//            mVideoPath.value = allPath
            advBanner.localPath = allPath
            addBanner(advBanner)
            downLoadAdvBanner((position + 1))


            return
        }
        HttpManager.getInstance("", null)
            .downloadFile(
                downloadUrl,
                filePath,
                downloadName,
                object : HttpManager.OnDownloadListener {
                    override fun onDownloadSuccess(path: String?) {
                        LogUtil.d("onDownloadSuccess:")


                        //下载成功后修改文件名（md5改成正式的）
                        val videoPath = FixFileName(downloadSavePath, fileName)
                        advBanner.localPath = allPath
                        addBanner(advBanner)
                        downLoadAdvBanner((position + 1))
//                    mVideoPath.value = videoPath
                    }

                    override fun onDownloading(progress: Int) {
                        LogUtil.d("progress:$progress")
                    }

                    override fun onDownloadFailed() {
                        downLoadAdvBanner((position + 1))
                        LogUtil.d("onDownloadFailed:")
                    }
                })
    }


    /**
     * 2 * 通过文件路径直接修改文件名
     * 3 *
     * 4 * @param filePath 需要修改的文件的完整路径
     * 5 * @param newFileName 需要修改的文件的名称 （如果不是文件夹，则需要带后缀名)
     * 6 * @return
     * 7
     */
    fun FixFileName(filePath: String, newFileName: String): String? {
        var newFileName = newFileName
        val f = File(filePath)
        if (!f.exists()) { // 判断原文件是否存在（防止文件名冲突）
            return null
        }
        newFileName = newFileName.trim { it <= ' ' }
        if (TextUtils.isEmpty(newFileName)) // 文件名不能为空
            return null
        var newFilePath: String? = null
        newFilePath = filePath.substring(0, filePath.lastIndexOf("/"))
        val file = File(newFilePath)
        if (!file.exists()) {
            file.mkdirs()
        }
        val nf = File(newFilePath, newFileName)
        try {
            f.renameTo(nf) // 修改文件名
        } catch (err: Exception) {
            err.printStackTrace()
            LogUtil.d("FixFileName Exception:$err")
            return null
        }
        return nf.path
    }


    private fun addBanner(bannerItem: BannerBean.BannerItem) {
        var isNeedAdd = true
        for (bannerItem2 in bannerItemList) {
            if (bannerItem2?.bannerImgurl == null) {
                continue
            }

            if (bannerItem2.bannerImgurl == bannerItem.bannerImgurl) {
                isNeedAdd = false
                break
            }
        }

        if (isNeedAdd) {
            bannerItemList.add(bannerItem)
        }
    }

    /**
     * 首先获取设备Token
     */
    fun report() {
        var map = mutableMapOf<String, Any?>()
        var iMachine = MachineFactory.getAutoCreate(mApplication)
        map["intranetIP"] = iMachine.ip
        map["imsi"] = iMachine.imsi
        map["totalStorage"] = iMachine.totalExternalMemorySize
        map["availableStorage"] = iMachine.availableExternalMemorySize
        map["temperature"] = iMachine.temperature
        map["humidity"] = iMachine.humidity
        map["lastRebootTime"] = MyApplication.rebootTime
        map["simIccid"] = getSerialNum()?:""
        map["simImei"] = getImei(mApplication, 0)?:""
        map["imsi"] = ""

        val url = "${HttpUrlManager.REPORT}"
        HttpManager.getInstance(
            "",
            HeaderInterceptor(MyApplication.instance.getHeaderMap())
        )
            .sendPost(url, map, object : MyRequestCallBack<Report>() {
                override fun onSuccess(obj: Report) {
                    if (obj.data != null) {
                        if (obj.data.newChange.isNewUpgrade) {
                            Log.e("TAG", "newUpgrade")
                            getUpgradeInfo(obj.data.newChange.newUpgradeUpdateTime as String)
                            SpUtils.putString(
                                SpUtils.NEW_UPGRADE_UPDATE_TIME,
                                obj.data.newChange.newUpgradeUpdateTime as String
                            )
                        }
                    }

                    when (obj?.code) {
                        RequestException.CODE_PERMISSION_DENIED,
                        RequestException.CODE_DEVICE_DID_NOT_REGISTER,
                        RequestException.CODE_DEVICE_TOKEN_INVALID,
                        RequestException.CODE_DEVICE_IS_FROZEN,
                        RequestException.CODE_COMPANY_OUT_OF_SERVICE -> {
                            SharedPreferencesUtils.saveBoolean("isBind", false)
                            reportResult.value = false
                        }

                        else -> {
                            SharedPreferencesUtils.saveBoolean("isBind", true)
                            reportResult.value = true
                            pollReportIntervalTime.value = obj.data.getmPollConfig()[0].pollIntervalTime
                            pollUpgradeIntervalTime.value = obj.data.getmPollConfig()[3].pollIntervalTime
                        }
                    }
                }

                override fun onFailure(error: Int, msg: String?) {

                }

            })
    }

    private fun getSerialNum(): String? {
        val telephonyManager =
            mApplication.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
        return telephonyManager.simSerialNumber
    }

    private fun getImei(context: Context, slotId: Int): String? {
        if (slotId != 0 && slotId != 1) {
            return null
        }
        val tm =
            context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
        return when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
                tm.getDeviceId(slotId)
            }
            slotId == 0 -> {
                tm.deviceId
            }
            else -> {
                val telephonyManager =
                    context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager // 取得相关系统服务
                var telephonyManagerClass: Class<*>? = null
                var imei: String? = null
                try {
                    telephonyManagerClass =
                        Class.forName("android.telephony.TelephonyManager")
                    val method: Method =
                        telephonyManagerClass.getMethod("getImei", Int::class.javaPrimitiveType)
                    imei = method.invoke(telephonyManager, slotId) as String
                } catch (e: java.lang.Exception) {
                    e.printStackTrace()
                }
                imei
            }
        }
    }

    private fun getUpgradeInfo(newUpgradeUpdateTime: String) {
        val local = SpUtils.getString(SpUtils.NEW_UPGRADE_UPDATE_TIME)
        if (TextUtils.equals(local, newUpgradeUpdateTime)) {
            return
        }
        SpUtils.putString(SpUtils.NEW_UPGRADE_UPDATE_TIME, newUpgradeUpdateTime)
        checkVersion()
    }

    fun getStoreInfo() {
        var url = HttpUrlManager.GET_STORE_INFO + "?lng=" + 0.0 + "&lat=" + 0.0
        HttpManager.getInstance("", HeaderInterceptor(MyApplication.instance.getHeaderMap()))
            .sendPost(
                url,
                HashMap(),
                object : MyRequestCallBack<StoreInfoEntity>() {
                    override fun onSuccess(obj: StoreInfoEntity) {
                        storeInfoEntity.value = obj
                        SpUtils.putString("storeName", obj.data.storeName)
                        SpUtils.putString("roomCode", obj.data.roomCode)
                        SpUtils.putInt("storeId", obj.data.storeId)
                    }

                    override fun onFailure(error: Int, msg: String?) {

                    }
                })
    }
}